package com.zhp.aspect;

import com.zhp.utils.CollectUtils;
import com.zhp.anno.Idempotent;
import com.zhp.ex.CustomException;
import com.zhp.helper.RedisHelper;
import com.zhp.keyresolver.IdempotentKeyResolver;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.util.Assert;

import java.util.List;
import java.util.Map;

/**
 * @author zhanghp
 * @since 2024/5/27 13:58
 */
@Slf4j
@Aspect
public class IdempotentAspect {

    private final Map<Class<? extends IdempotentKeyResolver>, IdempotentKeyResolver> keyResolvers;

    private final RedisHelper redisHelper;

    public IdempotentAspect(List<IdempotentKeyResolver> keyResolvers, RedisHelper redisHelper) {
        this.keyResolvers = CollectUtils.convertMap(keyResolvers, IdempotentKeyResolver::getClass);
        this.redisHelper = redisHelper;
    }

    @Pointcut("@annotation(idempotent)")
    public void pointcut(Idempotent idempotent) {
    }

    @Before("pointcut(idempotent)")
    public void before(JoinPoint joinPoint, Idempotent idempotent) {
        IdempotentKeyResolver resolver = keyResolvers.get(idempotent.keyResolver());
        Assert.notNull(resolver, "找不到对应的 IdempotentKeyResolver");
        String key = resolver.assembleKey(joinPoint, idempotent);
        if (!redisHelper.setnx(key, "", idempotent.timeout(), idempotent.timeunit())) {
            log.error("IdempotentAspect 参数[{}] 存在重复请求，幂等生效", key);
            throw new CustomException(idempotent.info());
        }
    }
}
